package com.yunyi.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yunyi.common.core.domain.AjaxResult;
import com.yunyi.common.core.domain.TreeSelect;
import com.yunyi.common.core.domain.entity.SysAreaA;
import com.yunyi.common.core.domain.entity.SysOffice;
import com.yunyi.common.utils.SecurityUtils;
import com.yunyi.common.utils.StringUtils;
import com.yunyi.common.utils.spring.SpringUtils;
import com.yunyi.system.mapper.SysAreaAMapper;
import com.yunyi.system.service.SysOfficeService;
import com.yunyi.system.mapper.SysOfficeMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author ZouLi
* @description 针对表【sys_office(机构表)】的数据库操作Service实现
* @createDate 2023-08-24 09:52:35
*/
@Service
public class SysOfficeServiceImpl extends ServiceImpl<SysOfficeMapper, SysOffice>
    implements SysOfficeService{

    /**
     * OfficeMapper
     **/
    @Autowired(required = false)
    private SysOfficeMapper officeMapper;

    /**
     * AreaMapper
     **/
    @Autowired(required = false)
    private SysAreaAMapper areaMapper;

    /**
     * @Description: 查询机构列表
     * @Param [office]
     * @Return java.util.List<com.yunyi.common.core.domain.entity.SysOffice>
     * @Throws
     **/
    @Override
    public List<SysOffice> selectOffices(SysOffice office) {
        List<SysOffice> offices = officeMapper.selectOffices(office);
        // 遍历
        offices.forEach(item -> {
            if (StringUtils.isNotNull(item.getArea_id()) && item.getParent_id() == 0) {
                List<SysAreaA> areas = areaMapper.getSysAreaById(item.getArea_id());
                item.setArea(areas.stream().map(SysAreaA::getName).collect(Collectors.joining(",")));
            }
        });
        return offices;
    }

    /**
     * @Description: 查询前端树状图数据
     * @Param []
     * @Return java.util.List<com.yunyi.common.core.domain.TreeSelect>
     * @Throws
     **/
    @Override
    public List<TreeSelect> selectOfficeTreeList(SysOffice office) {
        // 查询机构列表
        List<SysOffice> offices = SpringUtils.getAopProxy(this).selectOffices(office);
        // 构建树状图数据
        return buildOfficeTreeListData(offices);
    }

    /**
     * @Description: 构建前端树状图数据
     * @Param [office]
     * @Return java.util.List<com.yunyi.common.core.domain.TreeSelect>
     * @Throws
     **/
    @Override
    public List<TreeSelect> buildOfficeTreeListData(List<SysOffice> offices) {
        // 获取结构
        List<SysOffice> officeList = buildOfficeTree(offices);
        // 构建数据
        return officeList.stream().map(TreeSelect::new).collect(Collectors.toList());
    }

    /**
     * @Description: 构建前端树状结构
     * @Param [office]
     * @Return java.util.List<com.yunyi.common.core.domain.entity.SysOffice>
     * @Throws
     **/
    @Override
    public List<SysOffice> buildOfficeTree(List<SysOffice> offices) {
        // 获取所有机构的id
        List<Integer> ids = offices.stream().map(SysOffice::getId).collect(Collectors.toList());
        // 构建的机构列表
        List<SysOffice> returnOffices = new ArrayList<>();

        // 遍历未构建的机构列表
        for (SysOffice office : offices) {
            // 如果该机构是父级机构则查找其子级机构 (父级机构没有上级)
            if (!ids.contains(office.getParent_id())) {
                // 是否有子级
                if (hasChildren(offices, office)) {
                    // 设置子级机构
                    selectChildrenByParentOffice(offices, office);
                }
                // 添加
                returnOffices.add(office);
            }
        }
        if (returnOffices.isEmpty()) {
            returnOffices = offices;
        }
        return returnOffices;
    }

    /**
     * @Description: 根据父级机构在机构列表查询子级机构 (递归)
     * @Param [offices, parent]
     * @Return void
     * @Throws
     **/
    private void selectChildrenByParentOffice(List<SysOffice> offices, SysOffice parent) {
        // 获取子节点列表
        List<SysOffice> children = getChildren(offices, parent);
        // 将子级列表添加到父级机构
        parent.setChildren(children);
        // 遍历子级列表的子级列表
        for (SysOffice office : children) {
            if (hasChildren(offices, office)) {
                selectChildrenByParentOffice(offices, office);
            }
        }
    }

    /**
     * @Description: 获取子级列表
     * @Param [offices, parent]
     * @Return java.util.List<com.yunyi.common.core.domain.entity.SysOffice>
     * @Throws
     **/
    private List<SysOffice> getChildren(List<SysOffice> offices, SysOffice parent) {
        // 子级列表
        List<SysOffice> children = new ArrayList<>();
        Iterator<SysOffice> iterator = offices.iterator();
        while(iterator.hasNext()) {
            SysOffice office = iterator.next();
            // 判断是否属于父级机构
            if (StringUtils.isNotNull(office.getParent_id()) && office.getParent_id() == parent.getId()) {
                children.add(office);
            }
        }
        return children;
    }

    /**
     * @Description: 判断是否有子级菜单
     * @Param [offices, parent]
     * @Return boolean
     * @Throws
     **/
    private boolean hasChildren(List<SysOffice> offices, SysOffice parent){
        return getChildren(offices, parent).size() > 0;
    }


    /**
     * @Description: 查询父机构下的所有子机构（包括父机构）
     * @Param [parentId]
     * @Return java.util.List<com.yunyi.common.core.domain.entity.SysOffice>
     * @Throws
     **/
    @Override
    public List<SysOffice> selectOfficeByParentId(Integer parentId) {
        // 查询数据
        List<SysOffice> offices = officeMapper.selectOfficeByParentId(parentId);
        // 构建数据
        return buildOfficeTree(offices);
    }

    /**
     * @Description: 添加机构
     * @Param [office]
     * @Return java.lang.Boolean
     * @Throws
     **/
    @Override
    public Boolean addOffice(SysOffice office){
        // 如果为单位就不需要父级
        if (StringUtils.equals(office.getType(), "1")) {
            office.setParent_id(0);
        }

        StringBuffer str = new StringBuffer();
        SysOffice parentInfo = null;
        // 如果有父级id则获取父级id的parentIds并拼接进去
        if (office.getParent_id() != 0) {
            parentInfo = new SysOffice();
            parentInfo.setId(office.getParent_id());
            parentInfo = selectOffices(parentInfo).get(0);
            str.append(parentInfo.getParent_ids());
        }
        // 拼接父级列表
        str.append(office.getParent_id()+",");
        office.setParent_ids(str.toString());

        // 设置字段信息
        office.setCreateBy(SecurityUtils.getLoginUser().getUsername());
        office.setCreateTime(new Date());
        office.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
        office.setUpdateTime(new Date());
        return officeMapper.insert(office) > 0;
    }

    /**
     * @Description: 修改机构
     * @Param [office]
     * @Return java.lang.Boolean
     * @Throws
     **/
    @Override
    public Boolean updateOffice(SysOffice office) {
        // 如果为单位就不需要父级
        if (StringUtils.equals(office.getType(), "1")) {
            office.setParent_id(0);
        }

        String newParentIds = "";
        if (office.getParent_id() != 0) {
            SysOffice parentOffice = new SysOffice();
            parentOffice.setId(office.getParent_id());

            // 获取新的父级机构
            parentOffice = selectOffices(parentOffice).get(0);
            // 拼接新的父级列表
            newParentIds = parentOffice.getParent_ids()+parentOffice.getId()+",";
        }else {
            newParentIds = office.getParent_id()+",";
        }

        // 获取子级
        List<SysOffice> offices = officeMapper.selectOfficeByParentId(office.getId());
        int result = 0;
        for (SysOffice off : offices) {
            // 如果是当前需要修改的机构
            if (off.getId() == office.getId()) {
                office.setParent_ids(newParentIds);
                office.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
                office.setUpdateTime(new Date());
                if (officeMapper.updateById(office) > 0){ result++;}
            }else {
                off.setUpdateBy(SecurityUtils.getLoginUser().getUsername());
                off.setUpdateTime(new Date());
                off.setParent_ids(newParentIds+office.getId()+",");
                if (officeMapper.updateById(off) > 0) {result++;}
            }
        }
        return result == offices.size();
    }

    /**
     * @Description: 删除机构
     * @Param [id]
     * @Return java.lang.Boolean
     * @Throws
     **/
    @Override
    public Boolean deleteOffice(Integer id) {
        // 查找到当前机构和其子机构
        List<SysOffice> offices = officeMapper.selectOfficeByParentId(id);

        int result = 0;
        for (SysOffice office : offices) {
            office.setDel_flag("1");

            // 创建修改条件构造器
            UpdateWrapper<SysOffice> wrapper = new UpdateWrapper<>();
            wrapper.set("del_flag", "1")
                    .set("update_by", SecurityUtils.getLoginUser().getUsername())
                    .set("update_date", new Date())
                    .eq("id", office.getId());
            if (officeMapper.update(null, wrapper) > 0) { result++; }
        }
        return result == offices.size();
    }

    /**
     * @Description: 根据所属医院查询其部门
     * @Param [id]
     * @Return java.util.List<com.yunyi.common.core.domain.entity.SysOffice>
     * @Throws
     **/
    @Override
    public List<SysOffice> getOfficeByCompany(Integer id) {
        List<SysOffice> offices = officeMapper.selectOfficeByParentId(id);
        List<SysOffice> result = new ArrayList<SysOffice>();
        offices.forEach(item -> {
            if (item.getId() != id) {
                result.add(item);
            }
        });
        return result;
    }

    /**
     * 获取申请医院信息
     * @return
     */
    @Override
    public AjaxResult getApplayForHospital() {
        QueryWrapper sysOfficeQueryWrapper = new QueryWrapper<>()
                .eq("parent_id",0)
                .ne("id",1);
        List<SysOffice> applayForHospital = officeMapper.selectList(sysOfficeQueryWrapper);
        return applayForHospital == null ? AjaxResult.error("获取“申请医院”信息失败") : AjaxResult.success("获取“申请医院”信息成功",applayForHospital);
    }
}




